﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xml;

namespace WPFTools {
    public class VCXXmlTools {
        public delegate bool DeleteConditionDelegate(XmlNode xmlNode);
        private RichTextBox rtbLog;
        public VCXXmlTools(RichTextBox _rtblog) { 
            rtbLog = _rtblog;
        }
        private string baseSlnPath = "D:/VC/ObjectPRX 2024/sln/";
        /// <summary>
        /// 获取包含输入库列表的 AdditionalDependencies 的 XmlNode 节点
        /// </summary>
        /// <param name="xmlDoc"> 读取为 XmlDocument 的 vcxproj 文件 </param>
        /// <param name="isDebug"> 读取 Debug 配置还是 Release 配置 </param>
        /// <returns></returns>
        public XmlNode? GetOriginalInputLibsNode(XmlDocument xmlDoc, bool isDebug = true)
        {
            if (xmlDoc == null) { return null; }
            if (!xmlDoc.HasChildNodes)
            {
                return null;
            }

            XmlNode linkNode = null;

            foreach (XmlNode node in xmlDoc.ChildNodes)
            {
                if (!node.HasChildNodes)
                {
                    continue;
                }
                foreach (XmlNode node2 in node.ChildNodes)
                {
                    // 查找输入库节点位置
                    if (node2.Name == "ItemDefinitionGroup")
                    {
                        if (node2.Attributes == null)
                        {
                            continue;
                        }
                        foreach (XmlAttribute attr in node2.Attributes)
                        {
                            if (!attr.Value.Contains(isDebug ? "Debug" : "Release" + "|Win32"))
                            {
                                continue;
                            }
                            foreach (XmlNode itemDefinitionGroupChild in node2.ChildNodes)
                            {
                                if (itemDefinitionGroupChild.Name != "Link")
                                {
                                    continue;
                                }
                                linkNode = itemDefinitionGroupChild;
                                foreach (XmlNode linkChild in itemDefinitionGroupChild.ChildNodes)
                                {
                                    if (linkChild.Name != "AdditionalDependencies")
                                    {
                                        continue;
                                    }
                                    return linkChild;
                                }
                            }
                        }
                    }
                }
            }
            // 运行到此处说明没找到，所以创建一个
            if(linkNode == null) { return null; }
            XmlNode additionalDependenciesNode = xmlDoc.CreateElement("AdditionalDependencies", xmlDoc.DocumentElement.NamespaceURI);
            linkNode.AppendChild(additionalDependenciesNode);

            return additionalDependenciesNode;
        }
        public XmlNode? GetOriginalInputLibsNode(string xmlDocPath, bool isDebug = true) {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            return GetOriginalInputLibsNode(xmlDoc, isDebug);
        }
        public List<string>? GetOriginalInputLibsList(XmlDocument xmlDoc, bool isDebug = true)
        {
            if (xmlDoc == null) { return null; }
            XmlNode originInputLibsNode = GetOriginalInputLibsNode(xmlDoc);

            return originInputLibsNode.InnerText.Split(";").ToList();
        }

        /// <summary>
        /// 获取引用项目列表的 XmlNode
        /// </summary>
        /// <param name="xmlDoc"> 读取为 XmlDocument 的 vcxproj 文件 </param>
        /// <returns></returns>
        public XmlNode? GetNewDependenciesNode(string xmlDocPath)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if (xmlDoc == null) { return null; }
            if (!xmlDoc.HasChildNodes)
            {
                return null;
            }
            foreach (XmlNode node in xmlDoc.ChildNodes)
            {
                if (!node.HasChildNodes)
                {
                    continue;
                }
                foreach (XmlNode node2 in node.ChildNodes)
                {
                    // 删除 ProjectReference
                    for (int i = 0; i < node2.ChildNodes.Count; i++)
                    {
                        if (node2.ChildNodes[i].Name != "ProjectReference")
                        {
                            continue;
                        }
                        return node2;
                    }
                }
            }
            return null;
        }
        public List<string> GetDependenciesList(string xmlDocPath)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if (xmlDoc == null) { return null; }
            XmlNode dependenciesNode = GetNewDependenciesNode(xmlDocPath);
            if (dependenciesNode == null)
            {
                return new List<string>();
            }
            List<string> dependenciesStrList = new List<string>();
            foreach (XmlNode projectReferenceNode in dependenciesNode.ChildNodes)
            {
                foreach (XmlAttribute attribute in projectReferenceNode.Attributes)
                {
                    if (attribute.Name != "Include")
                    {
                        continue;
                    }
                    int startIndex = attribute.InnerText.LastIndexOf(@"\") + 1;
                    string result = attribute.InnerText.Substring(startIndex, attribute.InnerText.Length - startIndex - 8);
                    dependenciesStrList.Add(result);
                }
            }
            return dependenciesStrList;
        }

        /// <summary>
        /// 获取完整的输入库列表，带lib后缀
        /// </summary>
        /// <param name="xmlDoc"></param>
        /// <param name="isDebug"></param>
        /// <returns></returns>
        public List<string>? GetCompleteInputLibsList(string xmlDocPath, bool isDebug = true)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if (xmlDoc == null) { return null; }
            // 
            List<string> listOriginInputLibs = GetOriginalInputLibsList(xmlDoc);
            if (listOriginInputLibs == null)
            {
                Logger.WriteLog($"🔴项目 {xmlDocPath} 的输入库获取为空，用空列表代替。\n");
                listOriginInputLibs = new List<string>();
            }
            // 
            List<string> listDependencies = GetDependenciesList(xmlDocPath);
            if (listDependencies == null)
            {
                Logger.WriteLog($"🔴项目 {xmlDocPath} 的引用获取为空，用空列表代替。\n");
                listDependencies = new List<string>();
            }
            // 
            List<string> listComplete = new List<string>();
            listComplete.AddRange(listOriginInputLibs);
            listComplete.AddRange(listDependencies);
            // 除去不需要的元素
            listComplete = listComplete.Where(s =>
                !string.IsNullOrEmpty(s)
                && s != "%(AdditionalDependencies)"
            ).ToList();
            // 有的库不需要加 10 的后缀，直接就是 .lib，比如说 lib_json,
            // 所以这里直接先给他加好，然后再在下面的排除名单里加上
            var listLibsThatDoesNotNeed10Postfix = new List<string> { "lib_json" };
            listComplete = listComplete.Select((lib) =>
            {
                if (listLibsThatDoesNotNeed10Postfix.Contains(lib))
                {
                    return lib + ".lib";
                }
                return lib;
            }).ToList();
            // 给库加后缀
            string postfix = isDebug ? "10d.lib" : "10.lib";
            var listLibsThatDontModify = new List<string> { "SensAPI.lib", "acge17.lib", "acad.lib", "acdb17.lib", "acge17.lib", "lib_json.lib" };
            for (int i = 0; i < listComplete.Count; i++)
            {
                if (listLibsThatDontModify.Contains(listComplete[i]))
                {
                    continue;
                }
                else if (listComplete[i].EndsWith(".lib"))
                {
                    continue;
                }
                listComplete[i] = listComplete[i] + postfix;
            }
            // 
            return listComplete;
        }
        /// <summary>
        /// 将搜索目录如 IncludePath 等修改到新的
        /// </summary>
        /// <param name="xmlDocPath"></param>
        /// <param name="isDebug"></param>
        /// <returns></returns>
        public bool ModifyVCSearchDirectoriesToNew(string xmlDocPath, bool isDebug = true)
        {
            // TODO: 新增函数，修改搜索目录
            throw new NotImplementedException();
            return false;
        }

        public string? GetGuid(string xmlDocPath) {
            var result = XmlTools.SearchAllNodesByName(xmlDocPath, "ProjectGuid");
            if (result.Count == 0) {
                return null;
            }
            else {
                return result[0].InnerText;
            }
        }

        // 为本来没有依赖的项目添加依赖节点 ProjectReference 的父节点 ItemGroup
        public XmlNode? AddDependencyParentNode(XmlDocument xmlDoc) {
            var newNode = xmlDoc.CreateElement("ItemGroup",xmlDoc.DocumentElement.NamespaceURI);
            xmlDoc.DocumentElement.AppendChild(newNode);
            //
            return newNode;
        }
        public XmlNode? AddDependencyParentNode(string xmlDocPath) {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if (xmlDoc == null) { return null; }
            // 
            var result = AddDependencyParentNode(xmlDoc);
            xmlDoc.Save(xmlDocPath);
            return result;
        }

        /// <summary>
        /// 添加依赖项
        /// </summary>
        /// <param name="xmlDocPath"></param>
        /// <param name="targetProjectNameWithCode"></param>
        /// <returns></returns>
        public bool AddDependencies(XmlDocument xmlDoc, string targetProjectNameWithCode) {
            // 如果任意路径无效则退出
            if (string.IsNullOrEmpty(targetProjectNameWithCode)) {
                return false;
            }
            // 获取目标项目GUID
            string targetProjectPath = $"{this.baseSlnPath}{targetProjectNameWithCode}/{targetProjectNameWithCode}.vcxproj";
            if (string.IsNullOrEmpty(targetProjectPath) || !File.Exists(targetProjectPath)) {
                Logger.WriteLog($"找不到项目文件 {targetProjectPath}，请检查路径！\n", rtbLog, Colors.Red);
                return false;
            }
            string targetGuid = GetGuid(targetProjectPath);
            if (string.IsNullOrEmpty(targetGuid)) {
                Logger.WriteLog($"找不到项目 {targetProjectPath} 的GUID！\n", rtbLog, Colors.Red);
                return false;
            }
            // 生成要添加的节点
            var newNode = xmlDoc.CreateElement("ProjectReference", xmlDoc.DocumentElement.NamespaceURI);
            var newNodeAttribute = xmlDoc.CreateAttribute("Include");
            newNodeAttribute.Value = $"..\\{targetProjectNameWithCode}\\{targetProjectNameWithCode}.vcxproj";
            newNode.Attributes.Append(newNodeAttribute);
            var newNode2 = xmlDoc.CreateElement("Project", xmlDoc.DocumentElement.NamespaceURI);
            newNode2.InnerText = $"{targetGuid}";
            newNode.AppendChild(newNode2);
            // 找到插入点
            // 获取已有的依赖节点
            var listDependencies = XmlTools.SearchAllNodesByName(xmlDoc, "ProjectReference");
            // 如果没已有依赖
            XmlNode parentNode = null;
            if (listDependencies.Count == 0) {
                parentNode = this.AddDependencyParentNode(xmlDoc);
            }
            else {
                parentNode = listDependencies[0].ParentNode;
            }
            if (parentNode == null) {
                return false;
            }
            parentNode.AppendChild(newNode);
            // 
            return true;
        }
        public bool AddDependencies(string xmlDocPath, string targetProjectNameWithCode) {
            // 如果任意路径无效则退出
            if (!File.Exists(xmlDocPath) || string.IsNullOrEmpty(targetProjectNameWithCode)) {
                return false;
            }
            // 检查xml路径
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if (xmlDoc == null) { return false; }
            // 
            var result = AddDependencies(xmlDoc, targetProjectNameWithCode);
            xmlDoc.Save(xmlDocPath);
            return result;
        }
        public bool RemoveDependencies(XmlDocument xmlDoc, string targetProjectName) {
            // 如果任意路径无效则退出
            if (string.IsNullOrEmpty(targetProjectName)) {
                return false;
            }
            // 获取已有的依赖节点
            var listDependencies = XmlTools.SearchAllNodesByName(xmlDoc, "ProjectReference");
            if(listDependencies.Count==0) {
                Logger.WriteLog($"项目 {xmlDoc.BaseURI} 不存在依赖！", rtbLog, Colors.Yellow);
                return false; 
            }
            // 查找要删除的依赖节点
            XmlNode targetNode = null;
            foreach(var node in listDependencies) {
                bool isTarget = false;
                foreach(XmlAttribute attr in node.Attributes) {
                    if (attr.Value.Contains(targetProjectName+".vcxproj")) {
                        isTarget = true;
                        break;
                    }
                }
                if (isTarget) {
                    targetNode = node;
                    break;
                }
            }
            if(targetNode == null) {
                Logger.WriteLog($"没有在项目 {xmlDoc.BaseURI} 中找到要删除的 {targetProjectName} 依赖项！", rtbLog, Colors.Yellow);
                return false;
            }
            // 
            var parentNode = targetNode.ParentNode;
            parentNode.RemoveChild(targetNode);
            // 
            return true;
        }
        public bool RemoveDependencies(string xmlDocPath, string targetProjectName) {
            // 如果任意路径无效则退出
            if (!File.Exists(xmlDocPath) || string.IsNullOrEmpty(targetProjectName)) {
                return false;
            }
            // 检查xml路径
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if (xmlDoc == null) { return false; }
            // 
            var result = RemoveDependencies(xmlDoc, targetProjectName);
            xmlDoc.Save(xmlDocPath);
            return result;
        }

        public bool RemoveInputLibs(XmlDocument xmlDoc, string targetProjectName, bool isDebug = true) {
            var inputLibsNode = this.GetOriginalInputLibsNode(xmlDoc, isDebug);
            if (inputLibsNode == null) {
                throw new Exception("没有找到<OriginalInputLibs>节点！");
            }
            // 
            var match = Regex.Match(inputLibsNode.InnerText, @$"{targetProjectName}\w+.lib[;]*");
            if (!match.Success) {
                return false;
            }
            // 
            var targetLibToRemove = match.Groups[0].Value;
            inputLibsNode.InnerText = inputLibsNode.InnerText.Replace(targetLibToRemove, "");
            return true;
        }

        // 删除所有依赖项，因按标签名称查找，所以可能会遇到有问题的标签，此时会忽略该标签，并且不会报错，然后继续处理下一个
        public bool RemoveAllDependencies(XmlDocument xmlDoc, bool isIncludeInputLibs = false) {
            var referenceNodes = XmlTools.SearchAllNodesByName(xmlDoc, "ProjectReference");
            foreach (var node in referenceNodes) {
                if (node.ParentNode == null) {
                    continue;
                }
                node.ParentNode.RemoveChild(node);
            }

            if (isIncludeInputLibs) {
                var inputLibsNode = this.GetOriginalInputLibsNode(xmlDoc);
                if( inputLibsNode == null) {
                    throw new Exception("没有找到<OriginalInputLibs>节点！");
                }
                inputLibsNode.InnerText = "";
            }

            return true;
        }

        // 给新转换的新版项目设置VC++目录
        public bool AfterTransferToNew(XmlDocument xmlDoc, bool isDeleteAllInputLib = false, bool isDebug = true) {
            // 获取所有的 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 节点
            var dictAttrs = new Dictionary<string, string>();
            string debugOrRelease = isDebug ? "Debug" : "Release";
            dictAttrs.Add("Condition", $"'$(Configuration)|$(Platform)'=='{debugOrRelease}|Win32'");
            var listConfigNodes = XmlTools.SearchAllNodesByAttribute(xmlDoc, "PropertyGroup", dictAttrs);
            if (listConfigNodes.Count == 0) {
                Logger.WriteLog($"在项目文件 {xmlDoc.BaseURI} 里没有找到<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\"> 节点！", rtbLog, Colors.Red);
                return false;
            }
            // 再查看其下有没有<IncludePath>、<ReferencePath> 这些
            // 目前写的是只要发现有 IncludePath 就返回 true
            bool isVCPathAlreadyAdded = false;
            foreach (XmlNode node in listConfigNodes) {
                if(node.ChildNodes.Count==0) { 
                    continue;
                }
                foreach (XmlNode childNode in node.ChildNodes) {
                    if(childNode.Name== "IncludePath") {
                        isVCPathAlreadyAdded = true;
                    }
                }
            }
            // 已经设置了目录，所以不设置了
            if (isVCPathAlreadyAdded) {
                Logger.WriteLog($"该项目 {xmlDoc.BaseURI} 已经设置了目录！\n", rtbLog, Colors.Yellow);
                return false;
            }
            // 没设置的话就设置 listDependencies 是多个，但是其实在哪个下面设置都行
            var dictNewElement = new Dictionary<string, string>();
            dictNewElement.Add("IncludePath", "$(UESoftAutoPDMSIncludePath);$(IncludePath)");
            dictNewElement.Add("ReferencePath", "$(UESoftAutoPDMSReferencePath);$(ReferencePath)");
            dictNewElement.Add("LibraryPath", "$(UESoftAutoPDMSLibraryPath);$(LibraryPath)");
            dictNewElement.Add("ExcludePath", "$(UESoftAutoPDMSIgnorePath);$(ExcludePath)");

            // 必须添加到第二个Debug配置节点，也就是有LinkIncremental节点的那个，不然编译时会报找不到MFC头文件afxwin等的问题
            XmlNode nodeAddPos = null;
            foreach (var node in listConfigNodes) {
                foreach (XmlNode childNode in node.ChildNodes) {
                    if (childNode.Name == "LinkIncremental") {
                        nodeAddPos = node;
                        break;
                    }
                }
                if (nodeAddPos != null) {
                    break;
                }
            }
            if (nodeAddPos == null) {
                Logger.WriteLog($"未找到VC++Path应插入的XML节点！", rtbLog, Colors.Red);
                return false;
            }
            foreach (var item in dictNewElement) {
                var newElement = xmlDoc.CreateElement(item.Key, xmlDoc.DocumentElement.NamespaceURI);
                newElement.InnerText = item.Value;
                // 
                nodeAddPos.AppendChild(newElement);
            }

            string filepath = new Uri(xmlDoc.BaseURI).LocalPath;
            xmlDoc.Save(filepath);

            // 替换VC平台版本号
            string vcxprojContent = File.ReadAllText(filepath);
            vcxprojContent = Regex.Replace(vcxprojContent, @"\bv\d+\b", "v80");
            // 删除所有输入库
            if (isDeleteAllInputLib) {
                vcxprojContent = Regex.Replace(vcxprojContent, @"<AdditionalDependencies>.+</AdditionalDependencies>",
                    "<AdditionalDependencies></AdditionalDependencies>");
            }
            // 
            File.WriteAllText(filepath, vcxprojContent);


            // 
            return true;
        }
    }
}

